package net.atos.java.example.boodschappen.server;

import java.util.List;

import javax.servlet.http.HttpSession;

import net.atos.java.example.boodschappen.model.Boodschap;
import net.atos.java.example.boodschappen.model.Gebruiker;
import net.atos.java.example.boodschappen.persistence.BoodschapRepository;
import net.atos.java.example.boodschappen.persistence.GebruikerRepository;
import net.atos.java.example.boodschappen.persistence.impl.BoodschapJdoRepository;
import net.atos.java.example.boodschappen.persistence.impl.GebruikerJdoRepository;
import net.atos.java.example.boodschappen.shared.BoodschappenService;

import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * Boodschappen service implementatie.
 * 
 * @author Pal Hargitai
 */
public class BoodschappenServiceImpl extends RemoteServiceServlet implements
		BoodschappenService {

	/** Serial id. */
	private static final long serialVersionUID = -8506365806925698020L;
	/** Gebruiker sleutel. */
	private static final String USER_KEY = "boodschappen.user.key";
	/** Gebruiker service. */
	private UserService userService = UserServiceFactory.getUserService();
	/** Gebruiker repository. */
	private GebruikerRepository gebruikerRepository = new GebruikerJdoRepository();
	/** Boodschappen repository. */
	private BoodschapRepository boodschapRepository = new BoodschapJdoRepository();

	/**
	 * Haalt de gebruiker identificatie op.
	 * 
	 * @return De gebruiker identificatie.
	 */
	private String ophalenGebruikerId() {
		boolean userIsSet = false;
		HttpSession session = getThreadLocalRequest().getSession(true);
		// Test if the user key is set in the session.
		synchronized (session) {
			userIsSet = (session.getAttribute(USER_KEY) != null);
		}
		if (userIsSet) {
			synchronized (session) {
				return session.getAttribute(USER_KEY).toString();
			}
		} else {
			// Set the user in the session.
			User user = userService.getCurrentUser();
			String userId = user.getUserId();
			Gebruiker gebruiker = gebruikerRepository
					.vindGebruikerPerUserId(userId);
			String identificatie;
			if (gebruiker == null) {
				// Make a new user.
				gebruiker = new Gebruiker.Builder().id(user.getUserId())
						.naam(user.getNickname()).email(user.getEmail())
						.build();
				identificatie = gebruikerRepository.opslaan(gebruiker);
			} else {
				identificatie = gebruiker.getPk();
			}
			synchronized (session) {
				session.setAttribute(USER_KEY, identificatie);
			}
			return identificatie;
		}
	}

	/** {@inheritDoc} */
	@Override
	public List<Boodschap> ophalenBoodschappen() {
		return boodschapRepository.ophalenBoodschappen(ophalenGebruikerId());
	}

	/** {@inheritDoc} */
	@Override
	public void afvinkenBoodschap(String boodschapId) {
		boodschapRepository.verwijderen(boodschapId);
	}

	/** {@inheritDoc} */
	@Override
	public void mailBoodschappenlijst() {
		ophalenGebruikerId();
		String userId = ophalenGebruikerId();
		if (userId == null) {
			throw new IllegalStateException("Gebruiker niet ingelogged!");
		} else {
			// We maken een queue aan.
			Queue boodschappenQueue = QueueFactory
					.getQueue("boodschappen-queue");
			// We maken een task aan.
			TaskOptions options = TaskOptions.Builder
					.withUrl("/boodschappen-queue").param("user", userId)
					.method(Method.GET);
			// We ovegen een element toe aan de queue.
			boodschappenQueue.add(options);
		}

	}

	/** {@inheritDoc} */
	@Override
	public void toevoegenBoodschappen(List<Boodschap> boodschappen) {
		for (Boodschap boodschap : boodschappen) {
			String userId = ophalenGebruikerId();
			if (userId == null) {
				throw new IllegalStateException("Gebruiker niet ingelogged!");
			} else {
				boodschap.bewerkGebruiker(userId);
				this.boodschapRepository.bewerken(boodschap);
			}
		}
	}
}
